home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / RIP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-07  |  34.7 KB  |  1,254 lines

  1. /* This file contains code to implement the Routing Information Protocol (RIP)
  2.  * and is derived from 4.2BSD code. Mike Karels of Berkeley has stated on
  3.  * TCP-IP that the code may be freely used as long as UC Berkeley is
  4.  * credited. (Well, here's some credit :-). AGB 4-28-88
  5.  
  6.  * Further documentation on the RIP protocol is now available in Charles
  7.  * Hedrick's draft RFC, as yet unnumbered. AGB 5-6-88
  8.  *
  9.  * The RIP RFC has now been issued as RFC1058. AGB 7-23-88
  10.  *
  11.  * Code gutted and substantially rewritten. KA9Q 9/89
  12.  *
  13.  * Mods by PA0GRI
  14.  *
  15.  *  Changes Copyright (c) 1993 Jeff White - N0POY, All Rights Reserved.
  16.  *  Permission granted for non-commercial copying and use, provided
  17.  *  this notice is retained.
  18.  *
  19.  * Rehack for RIP-2 (RFC1388) by N0POY 4/1993
  20.  *  Modules needed for changes:  rip.c, rip.h, ripcmd.c, ripdump.c, ip.h
  21.  *                               commands.h, iface.h, iface.c, version.c
  22.  *
  23.  * Beta release 11/16/93 V0.95
  24.  *
  25.  * Bug fix that prevented split horizon routing to work fixed.
  26.  * 2/19/94 release V1.0
  27.  *
  28.  * G8BPQ's RIP98 added - G4HIP, 29/3/97
  29.  */
  30.  
  31. #include "global.h"
  32. #ifdef RIP
  33. #include <stdarg.h>
  34. #include <time.h>
  35. #include "mbuf.h"
  36. #include "netuser.h"
  37. #include "udp.h"
  38. #include "rip.h"
  39.  
  40. #if !defined(_lint)
  41. static char rcsid[] OPTIONAL = "$Id: rip.c,v 1.25 1997/09/07 21:18:28 root Exp root $";
  42. #endif
  43.  
  44. struct rip_stat Rip_stat = {{{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, 0, 0, 0, 0, 0, 0};
  45. int16 Rip_trace;
  46. FILE *Rip_trace_file = NULLFILE;
  47. char *Rip_trace_fname = NULLCHAR;
  48. int Rip_merge;
  49. int32 Rip_ttl = RIP_TTL;
  50. int16 Rip_ver_refuse = 0;
  51. int Rip_default_refuse = FALSE;
  52. int rip98allow = 1;
  53. struct rip_list *Rip_list;
  54. struct udp_cb *Rip_cb;
  55. struct rip_auth *Rip_auth;
  56. struct rip_refuse *Rip_refuse;
  57.  
  58. static int nbits (uint32 target);
  59. static void rip_trigger (void);
  60. static void rip_rx (struct iface * iface, struct udp_cb * sock, int16 cnt);
  61. static void proc_rip (struct iface * iface, uint32 gateway,
  62.     struct rip_route * ep, unsigned char version);
  63. static char *putheader (unsigned char *cp, char command, char version, int16 domain);
  64. static char *putentry (char *cp, int16 fam, int16 tag, uint32 target,
  65.     uint32 targmask, uint32 router, int32 metric);
  66. static char *put98entry (register char *cptr, uint32 target, int16 bits, int metric);
  67. static void send_routes (uint32 dest, int16 port, int trig,
  68.     int flags, unsigned char version, struct rip_list * rdata);
  69.  
  70. static void pullheader (struct rip_head * ep, struct mbuf ** bpp);
  71. static int check_authentication (struct rip_auth * auth,
  72.     struct mbuf ** bpp, struct rip_head * header, uint32 srcaddr, char const *ifcname,
  73.     struct rip_authenticate * entry);
  74. static char *putauth (char *cp, int16 authtype, char *authpass);
  75. static void rip_trace (short level, char const *errstr,...);
  76.  
  77.  
  78.  
  79. /* Send RIP CMD_RESPONSE packet(s) to the specified rip_list entry */
  80.  
  81. void
  82. rip_shout (void *p)
  83. {
  84. register struct rip_list *rl;
  85.  
  86.     rl = (struct rip_list *) p;
  87.     stop_timer (&rl->rip_time);
  88.     send_routes (rl->dest, RIP_PORT, 0, rl->flags, (unsigned char) rl->rip_version, rl);
  89.     set_timer (&rl->rip_time, rl->interval * 1000L);
  90.     start_detached_timer (&rl->rip_time);
  91. }
  92.  
  93.  
  94.  
  95. /* Send the routing table. */
  96. static void
  97. send_routes (dest, port, trig, flags, version, rdata)
  98. uint32 dest;            /* IP destination address to send to */
  99. int16 port;
  100. int trig;            /* Send only triggered updates? */
  101. int flags;
  102. unsigned char version;            /* Version of RIP packet */
  103. struct rip_list *rdata;        /* Used for RIP-2 packets */
  104. {
  105. char *cp;
  106. int i, bits, numroutes, maxroutes;
  107. int16 pktsize;
  108. int riplen = RIP_ENTRY;   
  109. struct mbuf *bp;
  110. struct route *rp;
  111. struct socket lsock, fsock;
  112. struct iface *iface;
  113.  
  114.     if (version == RIP_VERSION_98) { /* Fiddling to make RIP98 like latest official +1 */
  115.         version = RIP_VERSION_X;
  116.         riplen = RIP98_ENTRY;
  117.     }
  118.    
  119.     if ((rp = rt_lookup (dest)) == NULLROUTE) {
  120.         rip_trace (1, "No route to [%s] exists, cannot send", inet_ntoa (dest));
  121.         return;        /* No route exists, can't do it */
  122.     }
  123.     iface = rp->iface;
  124.  
  125.     /* Compute maximum packet size and number of routes we can send */
  126.     pktsize = ip_mtu (dest) - IPLEN;
  127.     pktsize = min (pktsize, RIP_PKTSIZE);
  128.     maxroutes = (pktsize - RIP_HEADER) / riplen;
  129.  
  130.     lsock.address = INADDR_ANY;
  131.     lsock.port = RIP_PORT;
  132.     fsock.address = dest;
  133.     fsock.port = port;
  134.  
  135.     /* Allocate space for a full size RIP packet and generate header */
  136.     if ((bp = alloc_mbuf (pktsize)) == NULLBUF)
  137.         return;
  138.     numroutes = 0;
  139.  
  140.     /* See if we know information about what to send out */
  141.  
  142.     if ((version >= RIP_VERSION_2) && (rdata != NULLRL) && (version != RIP_VERSION_X)) {
  143.         cp = putheader (bp->data, RIPCMD_RESPONSE, (char) version, rdata->domain);
  144.         /* See if we need to put an authentication header on */
  145.         if (flags & RIP_AUTHENTICATE) {
  146.             cp = putauth (cp, RIP_AUTH_SIMPLE, rdata->rip_auth_code);
  147.             numroutes++;
  148.         }
  149.     } else    {
  150.         if (version != RIP_VERSION_X)
  151.             cp = putheader (bp->data, RIPCMD_RESPONSE, (char) version, 0);
  152.         else
  153.             cp = putheader (bp->data, RIPCMD_RESPONSE, RIP_VERSION_98, 0);
  154.     }
  155.  
  156.     /* Emit route to ourselves, if requested */
  157.     if (flags & RIP_US) {
  158.         switch (version) {
  159.             case RIP_VERSION_1:
  160.                 cp = putentry (cp, RIP_AF_INET, 0, iface->addr, 0, 0, 1);
  161.                 break;
  162.  
  163.             case RIP_VERSION_X:
  164.                 cp = put98entry (cp, iface->addr, 32, 1);
  165.                 break;
  166.             default:
  167.                 cp = putentry (cp, RIP_AF_INET, 0, iface->addr, 0xFFFFFFFFUL, 0, 1);
  168.                 break;
  169.         }
  170.         numroutes ++;
  171.     }
  172.     /* Emit default route, if appropriate */
  173.  
  174.     if (R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)
  175.         && (!trig || (R_default.flags & RTTRIG))) {
  176.         if (!(flags & RIP_SPLIT) || iface != R_default.iface) {
  177.             switch (version) {
  178.                 case RIP_VERSION_1:
  179.                     cp = putentry (cp, RIP_AF_INET, 0, 0, 0, 0, R_default.metric);
  180.                     break;
  181.               
  182.                 case RIP_VERSION_X:
  183.                     cp = put98entry (cp, 0, 0, R_default.metric);
  184.                     break;
  185.               
  186.                 default:
  187.                     cp = putentry (cp, RIP_AF_INET, R_default.route_tag, 0, 0, 0, R_default.metric);
  188.                     break;
  189.             }
  190.             numroutes++;
  191.         } else if (trig && (flags & RIP_POISON)) {
  192.             /* Poisoned reverse */
  193.             switch (version) {
  194.                 case RIP_VERSION_1:
  195.                     cp = putentry (cp, RIP_AF_INET, 0, 0, 0, 0, RIP_METRIC_UNREACHABLE);
  196.                     break;
  197.  
  198.                 case RIP_VERSION_X:
  199.                     cp = put98entry (cp, 0, 0, RIP_METRIC_UNREACHABLE);
  200.                     break;
  201.               
  202.                 default:
  203.                     cp = putentry (cp, RIP_AF_INET, R_default.route_tag, 0, 0, 0, RIP_METRIC_UNREACHABLE);
  204.                     break;
  205.             }
  206.             numroutes++;
  207.         }
  208.     }
  209.     for (bits = 0; bits < 32; bits++) {
  210.         for (i = 0; i < HASHMOD; i++) {
  211.             for (rp = Routes[bits][i]; rp != NULLROUTE; rp = rp->next) {
  212.                 if ((rp->flags & RTPRIVATE) || (trig && !(rp->flags & RTTRIG)))
  213.                     continue;
  214.                     /* With RIP 98, don't send a host entries where we have it marked as GW */
  215.                 if ((version == RIP_VERSION_X) && (rp->gateway == dest))
  216.                     continue;
  217.  
  218.                 if (numroutes >= maxroutes) {
  219.                     /* Packet full, flush and make another */
  220.                     bp->cnt = (int16) (RIP_HEADER + numroutes * riplen);
  221.                     (void) send_udp (&lsock, &fsock, 0, 0, bp, bp->cnt, 0, 0);
  222.                     Rip_stat.vdata[(int) version].output++;
  223.                     if ((bp = alloc_mbuf (pktsize)) == NULLBUF)
  224.                         return;
  225.                     numroutes = 0;
  226.  
  227.                     if ((version >= RIP_VERSION_2) && (rdata != NULLRL) && (version != RIP_VERSION_X)) {
  228.                         cp = putheader (bp->data, RIPCMD_RESPONSE, (char) version,
  229.                             rdata->domain);
  230.                         /* See if we need to put an authentication header on */
  231.                         if (flags & RIP_AUTHENTICATE) {
  232.                             cp = putauth (cp, RIP_AUTH_SIMPLE, rdata->rip_auth_code);
  233.                             numroutes++;
  234.                         }
  235.                     } else    {
  236.                         if (version != RIP_VERSION_X)
  237.                             cp = putheader (bp->data, RIPCMD_RESPONSE, (char) version, 0);
  238.                         else
  239.                             cp = putheader (bp->data, RIPCMD_RESPONSE, RIP_VERSION_98, 0);
  240.                     }
  241.                 }
  242.                 if (!(flags & RIP_SPLIT) || iface != rp->iface) {
  243.                     switch (version) {
  244.                         case RIP_VERSION_1:
  245.                             cp = putentry (cp, RIP_AF_INET, 0, rp->target, 0, 0, rp->metric);
  246.                             break;
  247.  
  248.                         case RIP_VERSION_X:
  249.                             cp = put98entry (cp, rp->target, (int16) rp->bits, rp->metric);
  250.                             break;
  251.                       
  252.                         default:
  253.                             cp = putentry (cp, RIP_AF_INET, rp->route_tag, rp->target,
  254.                                 (0xFFFFFFFFUL << (32 - rp->bits)), rdata ? rdata->proxy_route : 0,
  255.                                 rp->metric);
  256.                             break;
  257.                     }
  258.                     numroutes++;
  259.                 } else if (trig && (flags & RIP_POISON)) {
  260.                     switch (version) { 
  261.                         case RIP_VERSION_1:
  262.                             cp = putentry (cp, RIP_AF_INET, 0, rp->target, 0, 0, RIP_METRIC_UNREACHABLE);
  263.                             break;
  264.                       
  265.                         case RIP_VERSION_X:
  266.                             cp = put98entry (cp, rp->target, (int16) rp->bits, RIP_METRIC_UNREACHABLE);
  267.                             break;
  268.                       
  269.                         default:
  270.                             cp = putentry (cp, RIP_AF_INET, rp->route_tag, rp->target,
  271.                                 (0xFFFFFFFFUL << (32 - rp->bits)), rdata ? rdata->proxy_route : 0,
  272.                                 RIP_METRIC_UNREACHABLE);
  273.                             break;
  274.                     }
  275.                     numroutes++;
  276.                 }
  277.             }
  278.         }
  279.     }
  280.     if (numroutes != 0) {
  281.         bp->cnt = (int16) (RIP_HEADER + numroutes * riplen);
  282.         (void) send_udp (&lsock, &fsock, 0, 0, bp, bp->cnt, 0, 0);
  283.         Rip_stat.vdata[(int) version].output++;
  284.     } else
  285.         free_p (bp);
  286. }
  287.  
  288.  
  289.  
  290. /* Add an entry to the rip broadcast list */
  291.  
  292. int
  293. rip_add (dest, interval, flags, version, authpass, domain, route_tag, proxy)
  294. uint32 dest;
  295. int32 interval;
  296. char flags;
  297. char version;
  298. char authpass[RIP_AUTH_SIZE];
  299. int16 domain;
  300. int16 route_tag;
  301. uint32 proxy;
  302. {
  303. register struct rip_list *rl;
  304. struct route *rp;
  305.  
  306.     for (rl = Rip_list; rl != NULLRL; rl = rl->next)
  307.         if ((rl->dest == dest) && (rl->domain == domain))
  308.             return 0;
  309.  
  310.     if ((rp = rt_lookup (dest)) == NULLROUTE) {
  311.         tprintf ("%s is unreachable\n", inet_ntoa (dest));
  312.         return 0;
  313.     }
  314.     /* get a chunk of memory for the rip interface descriptor */
  315.     rl = (struct rip_list *) callocw (1, sizeof (struct rip_list));
  316.  
  317.     /* tack this record on as the first in the list */
  318.     rl->next = Rip_list;
  319.     if (rl->next != NULLRL)
  320.         rl->next->prev = rl;
  321.     Rip_list = rl;
  322.  
  323.     rl->dest = dest;
  324.  
  325.     rip_trace (9, "Rip added V%d Flags %d Tag %d Proxy %s Domain %d Auth %s Interval %d",
  326.            version, flags, route_tag, inet_ntoa (proxy), domain, authpass, interval);
  327.  
  328.     /* and the interface ptr, tick interval and flags */
  329.     rl->iface = rp->iface;
  330.     rl->rip_version = version;
  331.     rl->interval = interval;
  332.     rl->flags = (int16) (int) flags;
  333.     rl->proxy_route = proxy;
  334.     rl->route_tag = route_tag;
  335.     rl->domain = domain;
  336.     memcpy (rl->rip_auth_code, authpass, RIP_AUTH_SIZE);
  337.  
  338.     /* and set up the timer stuff */
  339.     set_timer (&rl->rip_time, interval * 1000L);
  340.     rl->rip_time.func = rip_shout;
  341.     rl->rip_time.arg = rl;
  342.     start_detached_timer (&rl->rip_time);
  343.     return 1;
  344. }
  345.  
  346.  
  347.  
  348. /* add a gateway to the rip_refuse list which allows us to ignore their
  349.  * advertisements
  350.  */
  351.  
  352. int
  353. riprefadd (uint32 gateway)
  354. {
  355. register struct rip_refuse *rl;
  356.  
  357.     for (rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  358.         if (rl->target == gateway)
  359.             return 0;    /* Already in table */
  360.  
  361.     /* get a chunk of memory for the rip interface descriptor */
  362.     rl = (struct rip_refuse *) callocw (1, sizeof (struct rip_refuse));
  363.  
  364.     /* tack this record on as the first in the list */
  365.     rl->next = Rip_refuse;
  366.     if (rl->next != NULLREF)
  367.         rl->next->prev = rl;
  368.     Rip_refuse = rl;
  369.  
  370.     /* fill in the gateway to ignore */
  371.     rl->target = gateway;
  372.     return 0;
  373. }
  374.  
  375.  
  376.  
  377. /* Add an authentication type to an interface name */
  378.  
  379. int
  380. ripauthadd (char const *ifcname, int16 domain, char const *password)
  381. {
  382. register struct rip_auth *ra;
  383. int x;
  384.  
  385.     for (ra = Rip_auth; ra != NULLAUTH; ra = ra->next)
  386.         if (!strcmp (ifcname, ra->ifc_name) && (ra->domain == domain))
  387.             return 1;    /* Already in table */
  388.  
  389.     /* get a chunk of memory for the rip interface descriptor */
  390.     ra = (struct rip_auth *) callocw (1, sizeof (struct rip_auth));
  391.  
  392.     /* tack this record on as the first in the list */
  393.     ra->next = Rip_auth;
  394.     if (ra->next != NULLAUTH)
  395.         ra->next->prev = ra;
  396.     Rip_auth = ra;
  397.  
  398.     /* fill in the data */
  399.     ra->ifc_name = strdup (ifcname);
  400.     ra->domain = domain;
  401.     for (x = 0; x < RIP_AUTH_SIZE + 1; x++)
  402.         ra->rip_auth_code[x] = '\0';
  403.     strncpy (ra->rip_auth_code, password, RIP_AUTH_SIZE);
  404.     return 0;
  405. }
  406.  
  407.  
  408.  
  409. /* Drop an authentication to an interface name */
  410.  
  411. int
  412. ripauthdrop (char *ifcname, int16 domain)
  413. {
  414. register struct rip_auth *ra;
  415.  
  416.     for (ra = Rip_auth; ra != NULLAUTH; ra = ra->next)
  417.         if (!strcmp (ifcname, ra->ifc_name) && (ra->domain == domain))
  418.             break;
  419.  
  420.     /* leave if we didn't find it */
  421.     if (ra == NULLAUTH)
  422.         return 0;
  423.  
  424.     /* Unlink from list */
  425.     if (ra->next != NULLAUTH)
  426.         ra->next->prev = ra->prev;
  427.     if (ra->prev != NULLAUTH)
  428.         ra->prev->next = ra->next;
  429.     else
  430.         Rip_auth = ra->next;
  431.  
  432.     free ((char *) ra->ifc_name);
  433.     free ((char *) ra);
  434.     return 0;
  435. }
  436.  
  437.  
  438.  
  439. /* drop a RIP target */
  440.  
  441. int
  442. rip_drop (uint32 dest, int16 domain)
  443. {
  444. register struct rip_list *rl;
  445.  
  446.     for (rl = Rip_list; rl != NULLRL; rl = rl->next)
  447.         if ((rl->dest == dest) && (rl->domain == domain))
  448.             break;
  449.  
  450.     /* leave if we didn't find it */
  451.     if (rl == NULLRL)
  452.         return 0;
  453.  
  454.     /* stop the timer */
  455.     stop_timer (&rl->rip_time);
  456.  
  457.     /* Unlink from list */
  458.     if (rl->next != NULLRL)
  459.         rl->next->prev = rl->prev;
  460.     if (rl->prev != NULLRL)
  461.         rl->prev->next = rl->next;
  462.     else
  463.         Rip_list = rl->next;
  464.  
  465.     /* and deallocate the descriptor memory */
  466.     free ((char *) rl);
  467.     return 0;
  468. }
  469.  
  470.  
  471.  
  472. /* drop a RIP-refuse target from the rip_refuse list */
  473.  
  474. int
  475. riprefdrop (uint32 gateway)
  476. {
  477. register struct rip_refuse *rl;
  478.  
  479.     for (rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  480.         if (rl->target == gateway)
  481.             break;
  482.  
  483.     /* leave if we didn't find it */
  484.     if (rl == NULLREF)
  485.         return 0;
  486.  
  487.     /* Unlink from list */
  488.     if (rl->next != NULLREF)
  489.         rl->next->prev = rl->prev;
  490.     if (rl->prev != NULLREF)
  491.         rl->prev->next = rl->next;
  492.     else
  493.         Rip_refuse = rl->next;
  494.  
  495.     /* and deallocate the structure memory */
  496.     free ((char *) rl);
  497.     return 0;
  498. }
  499.  
  500.  
  501.  
  502. /* function to output a RIP CMD_RESPONSE packet for the rip_trigger list */
  503.  
  504. static void
  505. rip_trigger ()
  506. {
  507. register struct rip_list *rl;
  508. int bits, i;
  509. struct route *rp;
  510.  
  511.     for (rl = Rip_list; rl != NULLRL; rl = rl->next)
  512.         send_routes (rl->dest, RIP_PORT, 1, rl->flags, uchar(rl->rip_version), rl);
  513.  
  514.     /* Clear the trigger list */
  515.     R_default.flags &= ~RTTRIG;
  516.     for (bits = 0; bits < 32; bits++) {
  517.         for (i = 0; i < HASHMOD; i++) {
  518.             for (rp = Routes[bits][i]; rp != NULLROUTE; rp = rp->next)
  519.                 rp->flags &= ~RTTRIG;
  520.         }
  521.     }
  522. }
  523.  
  524.  
  525.  
  526. /* Start RIP agent listening at local RIP UDP port */
  527. int
  528. rip_init ()
  529. {
  530. struct socket lsock;
  531.  
  532.     lsock.address = INADDR_ANY;
  533.     lsock.port = RIP_PORT;
  534.  
  535.     if (Rip_cb == NULLUDP)
  536.         Rip_cb = open_udp (&lsock, rip_rx);
  537.  
  538.     Rip_trace = 0;
  539.  
  540.     /* Add the 0 domain with no password */
  541.  
  542.     (void) ripauthadd (DEFAULTIFC, 0, RIP_NO_AUTH);
  543.  
  544.     return 0;
  545. }
  546.  
  547.  
  548.  
  549. /* Process RIP input received from 'interface'. */
  550. static void
  551. rip_rx (struct iface *iface, struct udp_cb *sock, int16 cnt OPTIONAL)
  552. {
  553. int riplen = RIP_ENTRY;
  554. struct mbuf *bp;
  555. struct socket fsock;
  556. struct rip_refuse *rfl;
  557. struct rip_route entry;
  558. struct rip_head header;
  559. struct route *rp;
  560. struct rip_list *rl;
  561.    
  562.     /* receive the RIP packet */
  563.     (void) recv_udp (sock, &fsock, &bp);
  564.  
  565.     /* check the gateway of this packet against the rip_refuse list and
  566.      * discard it if a match is found
  567.      */
  568.  
  569.     for (rfl = Rip_refuse; rfl != NULLREF; rfl = rfl->next) {
  570.         if (fsock.address == rfl->target) {
  571.             Rip_stat.refusals++;
  572.             rip_trace (2, "RIP refused from %s", inet_ntoa (fsock.address));
  573.             free_p (bp);
  574.             return;
  575.         }
  576.     }
  577.  
  578.     pullheader (&header, &bp);
  579.  
  580.     /* This is a fiddle to make RIP98 look like latest rip +1 */
  581.     if (header.rip_vers == RIP_VERSION_98) {
  582.         header.rip_vers = RIP_VERSION_X;
  583.         riplen = RIP98_ENTRY;
  584.     }
  585.  
  586.     /* increment the rcvd cnt */
  587.     Rip_stat.vdata[header.rip_vers].rcvd++;
  588.  
  589.     /* Check to see if we'll accept this version on this interface */
  590.  
  591.     if (header.rip_vers <= Rip_ver_refuse) {
  592.         if (header.rip_vers != RIP_VERSION_X)
  593.             rip_trace (3, "RIP version %d refused from [%s]", header.rip_vers, inet_ntoa (fsock.address));
  594.         else
  595.             rip_trace (3, "RIP version %d refused from [%s]", RIP_VERSION_98, inet_ntoa (fsock.address));
  596.         Rip_stat.refusals++;
  597.         free_p (bp);
  598.         return;
  599.     }
  600.  
  601.     if ((header.rip_vers == RIP_VERSION_X) && rip98allow == 0) {
  602.         rip_trace (1, "RIP-98 frame received - rip98rx off");
  603.         Rip_stat.refusals++;
  604.         free_p(bp);
  605.         return;
  606.     }
  607.             
  608.     /* Check the version of the frame */
  609.     switch (header.rip_vers) {
  610.         case RIP_VERSION_2:
  611.             break;
  612.  
  613.         case RIP_VERSION_0:
  614.             rip_trace (1, "RIP Version 0 refused from [%s]", inet_ntoa (fsock.address));
  615.             Rip_stat.version++;
  616.             free_p (bp);
  617.             return;
  618.  
  619.         case RIP_VERSION_1:
  620.             /* Toss RIP if header is bogus for V1 */
  621.             if (header.rip_domain != 0) {
  622.                 rip_trace (1, "RIP-1 bogus header, data in null fields from [%s]",
  623.                        inet_ntoa (fsock.address));
  624.                 Rip_stat.vdata[RIP_VERSION_1].unknown++;
  625.                 free_p (bp);
  626.                 return;
  627.             }
  628.             break;
  629.        
  630.         case RIP_VERSION_X:
  631.                     
  632.             if (header.rip_cmd != RIPCMD_RESPONSE) {
  633.                 rip_trace (1, "RIP-98 invalid header received from [%s]\n", inet_ntoa (fsock.address));
  634.                 Rip_stat.vdata[RIP_VERSION_X].unknown++;
  635.                 free_p (bp);
  636.                 return;
  637.             }
  638.             break;
  639.         default:
  640.             break;
  641.     }
  642.         if (header.rip_vers != RIP_VERSION_X)
  643.         rip_trace (2, "RIP Packet version %d processing", header.rip_vers);
  644.     else
  645.         rip_trace (2, "RIP Packet version %d processing", RIP_VERSION_98);
  646.    
  647.     switch (header.rip_cmd) {
  648.         case RIPCMD_RESPONSE:
  649.             rip_trace (2, "RIPCMD_RESPONSE from [%s] domain %d", inet_ntoa (fsock.address),
  650.                    header.rip_domain);
  651.  
  652.             Rip_stat.vdata[header.rip_vers].response++;
  653.             if (header.rip_vers != RIP_VERSION_X)
  654.                 pullentry (&entry, &bp);
  655.             else
  656.                 pull98entry (&entry, &bp);
  657.  
  658.             if (header.rip_vers >= RIP_VERSION_2) {
  659.                 if (header.rip_vers != RIP_VERSION_X) {
  660.                     /* We still have the authentication entry from above */
  661.  
  662.                     if (!check_authentication (Rip_auth, &bp, &header, fsock.address,
  663.                         iface->name, (struct rip_authenticate *) &entry)) {
  664.                         free_p (bp);
  665.                         return;                   
  666.                     }
  667.                 }
  668.             }
  669.             proc_rip (iface, fsock.address, &entry, header.rip_vers);
  670.  
  671.             while (len_p (bp) >= riplen) {
  672.                 if (header.rip_vers != RIP_VERSION_X)
  673.                     pullentry (&entry, &bp);
  674.                 else
  675.                     pull98entry (&entry, &bp);
  676.  
  677.                 proc_rip (iface, fsock.address, &entry, header.rip_vers);
  678.             }
  679.  
  680.             /* If we can't reach the sender of this update, or if
  681.              * our existing route is not through the interface we
  682.              * got this update on, add him as a host specific entry
  683.              */
  684.             if ((rp = rt_blookup (fsock.address, 32)) != NULLROUTE)
  685.                 /* Host-specific route already exists, refresh it */
  686.                 start_detached_timer (&rp->timer);
  687.             else if ((rp = rt_lookup (fsock.address)) == NULLROUTE
  688.                  || rp->iface != iface) {
  689.                 entry.rip_family = RIP_AF_INET;
  690.                 entry.rip_tag = 0;
  691.                 entry.rip_dest = fsock.address;
  692.                 if (header.rip_vers > RIP_VERSION_1)
  693.                     entry.rip_dest_mask = 32;
  694.                 else
  695.                     entry.rip_dest_mask = 0;
  696.                 entry.rip_router = 0;
  697.                 entry.rip_metric = 0;    /* will get incremented to 1 */
  698.                 proc_rip (iface, fsock.address, &entry, header.rip_vers);
  699.             }
  700.             if (Rip_merge)
  701.                 rt_merge (Rip_trace);
  702.             rip_trigger ();
  703.             break;
  704.  
  705.         case RIPCMD_REQUEST:
  706.             rip_trace (2, "RIPCMD_REQUEST from [%s] domain %d", inet_ntoa (fsock.address),
  707.                    header.rip_domain);
  708.  
  709.             Rip_stat.vdata[header.rip_vers].request++;
  710.             /* For now, just send the whole table with split horizon
  711.              * enabled when the source port is RIP_PORT, and send
  712.              * the whole table with split horizon disable when another
  713.              * source port is used. This should be replaced with a more
  714.              * complete implementation that checks for non-global requests
  715.              */
  716.  
  717.             if (header.rip_vers > RIP_VERSION_1) {
  718.                 /* RIP-2, let's see if we know something about this guy */
  719.                 rp = rt_lookup (fsock.address);
  720.                 for (rl = Rip_list; rl != NULLRL; rl = rl->next)
  721.                     if ((rl->dest == rp->target) && (rl->domain == header.rip_domain))
  722.                         break;
  723.  
  724.                 if (rl == NULLRL)
  725.                     if (fsock.port == RIP_PORT)
  726.                         send_routes (fsock.address, fsock.port, 0, (RIP_BROADCAST | RIP_SPLIT |
  727.                             RIP_POISON), header.rip_vers, NULLRL);
  728.                     else
  729.                         send_routes (fsock.address, fsock.port, 0, (RIP_BROADCAST),
  730.                             header.rip_vers, NULLRL);
  731.                 else if (fsock.port == RIP_PORT)
  732.                     send_routes (fsock.address, fsock.port, 0, rl->flags, header.rip_vers, rl);
  733.                 else
  734.                     send_routes (fsock.address, fsock.port, 0, (rl->flags & ~(RIP_SPLIT | RIP_POISON)),
  735.                         header.rip_vers, rl);
  736.             } else {
  737.                 if (fsock.port == RIP_PORT)
  738.                     send_routes (fsock.address, fsock.port, 0, (RIP_SPLIT | RIP_BROADCAST | RIP_POISON),
  739.                         header.rip_vers, NULLRL);
  740.                 else
  741.                     send_routes (fsock.address, fsock.port, 0, RIP_BROADCAST,
  742.                         header.rip_vers, NULLRL);
  743.             }
  744.             break;
  745.  
  746.         default:
  747.             rip_trace (1, "RIPCMD Unknown or not implemented from [%s] command %d",
  748.                  inet_ntoa (fsock.address), header.rip_cmd);
  749.             Rip_stat.vdata[header.rip_vers].unknown++;
  750.             break;
  751.     }            /* switch */
  752.     free_p (bp);
  753. }
  754.  
  755.  
  756.  
  757. /* Apply a set of heuristics for determining the number of significant bits
  758.  * (i.e., the address mask) in the target address. Needed since RIP doesn't
  759.  * include the address mask for each entry.  Applies only to RIP-1 packets.
  760.  */
  761.  
  762. static int
  763. nbits (uint32 target)
  764. {
  765. int bits = 0;
  766.  
  767.     if (target == 0)
  768.         return 0;    /* Special case: 0.0.0.0 is the default route */
  769.  
  770.     /* Check the host-part bytes of
  771.      * the address to check for byte-wide zeros
  772.      * which we'll consider to be subnet routes.
  773.      * e.g.  44.80.0.0 will be considered to be equal to 44.80/16
  774.      * whereas 44.80.1.0 will be considered to be 44.80.1/24
  775.      */
  776.     switch (hibyte (hiword (target)) >> 6) {
  777.         case 3:    /* Class C address */
  778.             /* is it a host address ? i.e. are there any 1's in the host part ? */
  779.             if (target & 0xff)
  780.                 bits = 32;
  781.             else
  782.                 bits = 24;
  783.             break;
  784.         case 2:    /* Class B address */
  785.             if (target & 0xff)
  786.                 bits = 32;
  787.             else if (target & 0xff00)
  788.                 bits = 24;
  789.             else
  790.                 bits = 16;
  791.             break;
  792.         case 0:    /* Class A address */
  793.         case 1:
  794.         default:
  795.             if (target & 0xff)
  796.                 bits = 32;
  797.             else if (target & 0xff00)
  798.                 bits = 24;
  799.             else if (target & 0xff0000L)
  800.                 bits = 16;
  801.             else
  802.                 bits = 8;
  803.     }
  804.  
  805.     return bits;
  806. }
  807.  
  808.  
  809.  
  810. /* Remove and process a RIP response entry from a packet */
  811.  
  812. static void
  813. proc_rip (struct iface *iface, uint32 gateway, register struct rip_route *ep, unsigned char version)
  814. {
  815. int32 interval;
  816. uint32 target;
  817. unsigned int bits;
  818. register struct route *rp;
  819. struct rip_list *rl;
  820. int add = 0;        /* action flags */
  821. int drop = 0;
  822. int trigger = 0;
  823.  
  824.     if (ep->rip_family != RIP_AF_INET) {
  825.         if (ep->rip_family == RIP_AF_AUTH)
  826.             return;
  827.         /* Skip non-IP addresses */
  828.         rip_trace (1, "RIP_rx: Not an IP family packet\n");
  829.         Rip_stat.addr_family++;
  830.         return;
  831.     }
  832.  
  833.     /* RIP-1 says all unused fields must be zero */
  834.     if (version == RIP_VERSION_1) {
  835.         if (ep->rip_tag != 0 || ep->rip_dest_mask != 0 || ep->rip_router != 0) {
  836.             rip_trace (1, "RIP_rx: RIP-1 entry bad, data in null fields");
  837.             Rip_stat.vdata[version].unknown++;
  838.         }
  839.         /* Guess at the mask, since it's not explicit for RIP-1 */
  840.         bits = (unsigned int) nbits (ep->rip_dest);
  841.         target = ep->rip_dest;
  842.     } else {
  843.         /* Assume RIP-2 */
  844.         if (!ep->rip_dest_mask) {
  845.             /* No netmask, guess */
  846.             bits = (unsigned int) nbits (ep->rip_dest);
  847.         } else
  848.             bits = (unsigned int) mask2width (ep->rip_dest_mask);
  849.         target = ep->rip_dest;
  850.         /* Check for "proxy" rip */
  851.         if (ep->rip_router) {
  852.             rip_trace (3, "Proxy rip pointing to [%s]", inet_ntoa (ep->rip_router));
  853.             gateway = ep->rip_router;
  854.         }
  855.     }
  856.  
  857.     /* Don't ever add a route to myself through somebody! */
  858.     if (bits == 32 && ismyaddr (target) != NULLIF) {
  859.         rip_trace (2, "Route to self [%s]/32 metric %lu", inet_ntoa (target),
  860.                ep->rip_metric);
  861.         return;
  862.     }
  863.     /* Check to see if we'll take a default route, zero bits mean default */
  864.  
  865.     if (Rip_default_refuse && bits == 0) {
  866.         rip_trace (2, "Default route refused from [%s]", inet_ntoa (target));
  867.         return;
  868.     }
  869.     /* Update metric to reflect link cost */
  870.     ep->rip_metric += iface->iface_metric;
  871.     ep->rip_metric = min (ep->rip_metric, RIP_METRIC_UNREACHABLE);
  872.  
  873.     /* Find existing entry, if any */
  874.     rp = rt_blookup (target, bits);
  875.  
  876.     /* Don't touch private routes */
  877.     if (rp != NULLROUTE && (rp->flags & RTPRIVATE)) {
  878.         rip_trace (3, "Route to [%s]/%u unchanged, private", inet_ntoa (target),
  879.                bits);
  880.         return;
  881.     }
  882.         if (rp == NULLROUTE) {
  883.         if (ep->rip_metric < RIP_METRIC_UNREACHABLE) {
  884.             /* New route; add it and trigger an update */
  885.             add++;
  886.             trigger++;
  887.         }
  888.     } else if (rp->metric == RIP_METRIC_UNREACHABLE) {
  889.         /* Route is in hold-down; ignore this guy */
  890.         rip_trace (2, "Route to [%s]/%u ignored (hold-down) metric %lu",
  891.                inet_ntoa (target), bits, ep->rip_metric);
  892.     } else if (rp->gateway == gateway && rp->iface == iface) {
  893.         /* This is the gateway for the entry we already have, restart the timer */
  894.         start_detached_timer (&rp->timer);
  895.         if (rp->metric != ep->rip_metric) {
  896.             /* Metric has changed. Update it and trigger an
  897.              * update. If route has become unavailable, start
  898.              * the hold-down timeout.
  899.              */
  900.             rip_trace (3, "Metric change [%s]/%u %lu -> %lu", inet_ntoa (target),
  901.                    bits, rp->metric, ep->rip_metric);
  902.             if (ep->rip_metric == RIP_METRIC_UNREACHABLE)
  903.                 rt_timeout (rp);    /* Enter hold-down timeout */
  904.             else
  905.                 rp->metric = ep->rip_metric;
  906.             trigger++;
  907.         }
  908.     } else {
  909.         /* Entry is from a different gateway than the current route */
  910.         if (ep->rip_metric < rp->metric) {
  911.             /* Switch to a new gateway */
  912.             rip_trace (3, "Metric better [%s]/%u new: %lu old: %lu", inet_ntoa (target),
  913.                    bits, ep->rip_metric, rp->metric);
  914.             drop++;
  915.             add++;
  916.             trigger++;
  917.         } else {
  918.             /* Metric is no better, stay with current route */
  919.             rip_trace (3, "Metric not better [%s]/%u new: %lu old: %lu", inet_ntoa (target),
  920.                    bits, ep->rip_metric, rp->metric);
  921.         }
  922.     }
  923.     if (drop) {
  924.         /* Switching to a better gateway; delete old entry */
  925.         rip_trace (2, "Route drop [%s]/%u", inet_ntoa (target), bits);
  926.         (void) rt_drop (target, bits);
  927.     }
  928.     if (add) {
  929.         /* Add a new entry */
  930.         interval = Rip_ttl;
  931.         for (rl = Rip_list; rl != NULLRL; rl = rl->next) {
  932.             if (rl->iface == iface) {
  933.                 interval = rl->interval * 4;
  934.                 break;
  935.             }
  936.         }
  937.         rip_trace (2, "Route add [%s]/%u through %s via ",
  938.                inet_ntoa (target), bits, iface->name);
  939.         rip_trace (2, "[%s] metric %lu", inet_ntoa (gateway),
  940.                ep->rip_metric);
  941.  
  942.         rp = rt_add (target, (unsigned) bits, gateway, iface,
  943.                  (int) ep->rip_metric, interval, 0);
  944.  
  945.         /* Add in the routing tag for RIP-2 */
  946.  
  947.         if (version >= RIP_VERSION_2)
  948.             rp->route_tag = ep->rip_tag;
  949.         else
  950.             rp->route_tag = 0;
  951.     }
  952.     /* If the route changed, mark it for a triggered update */
  953.     if (trigger && rp)
  954.         rp->flags |= RTTRIG;
  955. }
  956.  
  957.  
  958.  
  959. /* Send a RIP request packet to the specified destination */
  960.  
  961. int
  962. ripreq (uint32 dest, int16 replyport, int16 version)
  963. {
  964. struct mbuf *bp;
  965. struct socket lsock, fsock;
  966. char *cp;
  967. register struct rip_list *rl;
  968.  
  969.     lsock.address = INADDR_ANY;
  970.     lsock.port = replyport;
  971.  
  972.     /* if we were given a valid dest addr, ask it (the routers on that net)
  973.      * for a default gateway
  974.      */
  975.  
  976.     if (dest == 0)
  977.         return 0;
  978.  
  979.     fsock.address = dest;
  980.     fsock.port = RIP_PORT;
  981.  
  982.     /* Send out one RIP Request packet as a broadcast to 'dest'  */
  983.     if ((bp = alloc_mbuf (RIP_HEADER + RIP_ENTRY)) == NULLBUF)
  984.         return -1;
  985.  
  986.     /* Check to see if we already know something about who we're   */
  987.     /* requesting the RIP from */
  988.  
  989.     for (rl = Rip_list; rl != NULLRL; rl = rl->next)
  990.         if (rl->dest == dest)
  991.             break;
  992.  
  993.     bp->cnt = RIP_HEADER + RIP_ENTRY;
  994.     if (rl != NULLRL) {
  995.         cp = putheader (bp->data, RIPCMD_REQUEST, rl->rip_version, rl->domain);
  996.         if (rl->rip_version >= RIP_VERSION_2) {
  997.             if (rl->flags & RIP_AUTHENTICATE) {
  998.                 cp = putauth (cp, RIP_AUTH_SIMPLE, rl->rip_auth_code);
  999.                 bp->cnt += RIP_ENTRY;
  1000.             }
  1001.         }
  1002.         Rip_stat.vdata[(int) rl->rip_version].output++;
  1003.     } else {
  1004.         cp = putheader (bp->data, RIPCMD_REQUEST, (char) version, 0);
  1005.         Rip_stat.vdata[version].output++;
  1006.     }
  1007.  
  1008.     cp = putentry (cp, 0, 0, 0L, 0L, 0L, RIP_METRIC_UNREACHABLE);
  1009.     (void) send_udp (&lsock, &fsock, 0, 0, bp, bp->cnt, 0, 0);
  1010.     return 0;
  1011. }
  1012.  
  1013.  
  1014.  
  1015. /* Write the authentication packet */
  1016.  
  1017. static char *
  1018. putauth (register char *cptr, int16 authtype, char *authpass)
  1019. {
  1020. int x;
  1021. unsigned char *cp = (unsigned char *) cptr;
  1022.  
  1023.     cp = put16 (cp, 0xFFFF);
  1024.     cp = put16 (cp, authtype);
  1025.  
  1026.     /* Put the password in big-endian (network) byte order */
  1027.     /* This probably is not the best way to do this, since it */
  1028.     /* would hose up on a real big-endian machine.  Oh well */
  1029.     /* Something to fix in the future.  Whip me, beat me, make */
  1030.     /* me use an Intel micro brain.  -N0POY */
  1031.  
  1032.     for (x = 0; x < RIP_AUTH_SIZE; x += 4) {
  1033.         *cp++ = uchar (authpass[x + 3]);
  1034.         *cp++ = uchar (authpass[x + 2]);
  1035.         *cp++ = uchar (authpass[x + 1]);
  1036.         *cp++ = uchar (authpass[x]);
  1037.     }
  1038.     return ((char *) cp);
  1039. }
  1040.  
  1041.  
  1042.  
  1043. /* Write the header of a RIP packet */
  1044.  
  1045. static char *
  1046. putheader (register unsigned char *cp, char command, char version, int16 domain)
  1047. {
  1048.     *cp++ = uchar(command);
  1049.     *cp++ = uchar(version);
  1050.     return (char *) put16 ((unsigned char *) cp, domain);
  1051. }
  1052.  
  1053.  
  1054.  
  1055. /* Write a single entry into a rip packet */
  1056.  
  1057. static char *
  1058. putentry (register char *cptr, int16 fam, int16 tag, uint32 target, uint32 targmask,
  1059.       uint32 router, int32 metric)
  1060. {
  1061. unsigned char *cp = (unsigned char *) cptr;
  1062.  
  1063.     cp = put16 (cp, fam);
  1064.     cp = put16 (cp, tag);
  1065.     cp = put32 (cp, target);
  1066.     cp = put32 (cp, targmask);
  1067.     cp = put32 (cp, router);
  1068.     return (char *) put32 (cp, (unsigned long) metric);
  1069. }
  1070.  
  1071.  
  1072.  
  1073. /* Write a single entry into a rip98 packet */
  1074.  
  1075. static char *
  1076. put98entry (register char *cptr, uint32 target, int16 bits, int metric)
  1077. {
  1078. unsigned char *cp = (unsigned char *) cptr;
  1079.  
  1080.     cp = put32 (cp, target);
  1081.     *cp++ = uchar (bits);
  1082.     *cp++ = uchar (metric);
  1083.     return (char *) cp;
  1084. }
  1085.  
  1086.  
  1087.  
  1088. /* Check the authentication of RIP-II packets */
  1089. int
  1090. check_authentication (struct rip_auth *auth, struct mbuf **bpp OPTIONAL, struct rip_head *header,
  1091.     uint32 srcaddr, char const *ifcname, struct rip_authenticate *entry)
  1092. {
  1093. struct rip_auth *rd;
  1094.  
  1095.     for (rd = auth; rd != NULLAUTH; rd = rd->next) {
  1096.         if ((strcmp (ifcname, rd->ifc_name) == 0) ||
  1097.             (strcmp (DEFAULTIFC, rd->ifc_name) == 0)) {
  1098.             if (rd->domain == header->rip_domain) {
  1099.                 /* We'll take this domain, check against a NULL password */
  1100.                 if (strcmp (rd->rip_auth_code, RIP_NO_AUTH) == 0) {
  1101.                     rip_trace (3, "RIP-2 taken due to no password from [%s] domain %d",
  1102.                            inet_ntoa (srcaddr), header->rip_domain);
  1103.                     return (TRUE);
  1104.                 } else {
  1105.  
  1106.                     /* Okay, we need an authentication */
  1107.  
  1108.                     if (entry->rip_family != RIP_AF_AUTH) {
  1109.                         /* It doesn't have an authentication packet */
  1110.                         rip_trace (2, "RIP-2 lacking authentication packet from [%s] domain %d",
  1111.                                inet_ntoa (srcaddr), header->rip_domain);
  1112.                         Rip_stat.auth_fail++;
  1113.                         return (FALSE);
  1114.                     }
  1115.                     if (entry->rip_auth_type != RIP_AUTH_SIMPLE) {
  1116.                         /* Only support simple authentication */
  1117.                         rip_trace (2, "RIP-2 wrong type of authentication from [%s]",
  1118.                                inet_ntoa (srcaddr));
  1119.                         Rip_stat.auth_fail++;
  1120.                         return (FALSE);
  1121.                     }
  1122.                     if (memcmp (rd->rip_auth_code, entry->rip_auth_str, RIP_AUTH_SIZE) == 0) {
  1123.                         rip_trace (3, "RIP-2 authenticated from [%s] domain %d",
  1124.                                inet_ntoa (srcaddr), header->rip_domain);
  1125.                         return (TRUE);
  1126.                     } else {
  1127.                         rip_trace (2, "RIP-2 authentication failed from [%s] domain %d,\n attempted password '%.16s' right password '%.16s'",
  1128.                                inet_ntoa (srcaddr), header->rip_domain, entry->rip_auth_str, rd->rip_auth_code);
  1129.                         Rip_stat.auth_fail++;
  1130.                         return (FALSE);
  1131.                     }
  1132.                 }
  1133.             }
  1134.         }
  1135.     }
  1136.     /* Didn't find the right routing domain for this packet */
  1137.     rip_trace (3, "RIP-2 domain %d not accepted from [%s]", header->rip_domain,
  1138.            inet_ntoa (srcaddr));
  1139.     Rip_stat.wrong_domain++;
  1140.     return (FALSE);
  1141. }
  1142.  
  1143.  
  1144.  
  1145. /* Route timeout handler. If route has already been marked for deletion
  1146.  * then delete it. Otherwise mark for deletion and restart timer.
  1147.  */
  1148. void
  1149. rt_timeout (void *s)
  1150. {
  1151. register struct route *rp = (struct route *) s;
  1152.  
  1153.     stop_timer (&rp->timer);
  1154.     if (rp->metric < RIP_METRIC_UNREACHABLE) {
  1155.         rip_trace (5, "RIP:  route to [%s]/%d expired - hold down", inet_ntoa (rp->target),
  1156.                rp->bits);
  1157.         rp->metric = RIP_METRIC_UNREACHABLE;
  1158.         if (dur_timer (&rp->timer) == 0)
  1159.             set_timer (&rp->timer, Rip_ttl * 1000L);
  1160.         /* wait 2/3 of timeout before garbage collect */
  1161.         set_timer (&rp->timer, dur_timer (&rp->timer) * 2 / 3);
  1162.         rp->timer.func = rt_timeout;
  1163.         rp->timer.arg = (void *) rp;
  1164.         start_detached_timer (&rp->timer);
  1165.         /* Route changed; mark it for triggered update */
  1166.         rp->flags |= RTTRIG;
  1167.         rip_trigger ();
  1168.     } else {
  1169.         rip_trace (5, "RIP:  route to [%s]/%d expired - dropped", inet_ntoa (rp->target),
  1170.                rp->bits);
  1171.         (void) rt_drop (rp->target, rp->bits);
  1172.     }
  1173. }
  1174.  
  1175.  
  1176.  
  1177. void
  1178. pullheader (struct rip_head *ep, struct mbuf **bpp)
  1179. {
  1180.     ep->rip_cmd = uchar(pullchar (bpp));
  1181.     ep->rip_vers = uchar(pullchar (bpp));
  1182.     ep->rip_domain = pull16 (bpp);
  1183. }
  1184.  
  1185.  
  1186.  
  1187. void
  1188. rip_trace (short level, char const *errstr,...)
  1189. {
  1190.     if ((int16) level <= Rip_trace) {
  1191.         char *timestr;
  1192.         time_t timer;
  1193.         va_list argptr;
  1194.  
  1195.         if (Rip_trace_fname != NULLCHAR) {
  1196.             (void) time (&timer);
  1197.             timestr = ctime (&timer);
  1198.             timestr[24] = '\0';
  1199.             Rip_trace_file = fopen (Rip_trace_fname, APPEND_TEXT);
  1200.             fprintf (Rip_trace_file, "%s - ", timestr);
  1201.  
  1202.             va_start (argptr, errstr);        /*lint !e718 !e746 */
  1203.             (void) vfprintf (Rip_trace_file, errstr, argptr);
  1204.             va_end (argptr);
  1205.             fprintf (Rip_trace_file, "\n");
  1206.             (void) fclose (Rip_trace_file);
  1207.         } else {
  1208.             va_start (argptr, errstr);
  1209.             (void) usvprintf (Curproc->output, errstr, argptr);
  1210.             va_end (argptr);
  1211.             tprintf ("\n");
  1212.         }
  1213.     }
  1214. }
  1215.  
  1216.  
  1217.  
  1218. void
  1219. pullentry (register struct rip_route *ep, struct mbuf **bpp)
  1220. {
  1221.     ep->rip_family = pull16 (bpp);
  1222.     ep->rip_tag = pull16 (bpp);
  1223.     ep->rip_dest = pull32 (bpp);
  1224.     ep->rip_dest_mask = pull32 (bpp);
  1225.     ep->rip_router = pull32 (bpp);
  1226.     ep->rip_metric = (long) pull32 (bpp);
  1227. }
  1228.  
  1229.  
  1230.  
  1231. /* Pulls a RIP98 Entry and converts to "more standard" RIP */
  1232. void
  1233. pull98entry (register struct rip_route *ep, struct mbuf **bpp)
  1234. {
  1235. unsigned int mask_bits;
  1236. int metric_bits;   
  1237.  
  1238.     ep->rip_family = RIP_AF_INET;
  1239.     ep->rip_tag = 0;
  1240.     ep->rip_dest = pull32 (bpp);
  1241.     mask_bits = (unsigned int) pullchar (bpp);
  1242.     metric_bits = pullchar (bpp);
  1243.     ep->rip_dest_mask = (0xffffffffLU << (32-mask_bits));
  1244.     ep->rip_metric = metric_bits;
  1245.     ep->rip_router = 0;
  1246.  
  1247. #if 0        /* Used in debugging, but left for anyone who has need ! */
  1248.     rip_trace (9, "Rip98: Destination [%s] : mask %d : metric %d", inet_ntoa( ep->rip_dest), mask_bits, metric_bits);
  1249. #endif
  1250. }
  1251.  
  1252.  
  1253. #endif /* RIP */
  1254.